import curses
import sys
import re

# 定义列标签
columns = "ABCDEFGHJKLMNOPQRST"  # 围棋棋盘的列标签

def parse_sgf(sgf_content):
    # 逐行读取SGF文件内容
    lines = sgf_content.strip().split(';')
    moves = []
    
    # 跳过第一行（通常是棋谱的元数据），解析后续的棋步
    for line in lines[1:]:
        if line.startswith('B[') or line.startswith('W['):
            # 提取棋步坐标
            match = re.search(r"[A-T][1-9][0-9]?", line[2:])
            if not match:
                print(f"Warning: Invalid move format: {line}")
                continue
            moves.append(match.group(0))
    
    return moves

def coord_to_board(coord):
    # 将SGF坐标转换为棋盘上的行和列索引
    # SGF中，A=0, B=1, ..., T=18
    try:
        col = columns.index(coord[0].upper())
        row = int(coord[1:]) - 1  # 行号从1到19，SGF也是从1到19
        return row, col
    except (ValueError, IndexError):
        print(f"Warning: Invalid coordinate: {coord}")
        return None, None

def draw_board(stdscr, board, current_move, total_moves, current_color, current_move_info):
    # 清除屏幕
    stdscr.clear()
    
    # 打印列标
    col_labels = "   " + " ".join(columns)
    stdscr.addstr(0, 0, col_labels)
    
    for row in range(19):
        # 行号从上到下，i=0 对应棋盘的第1行
        screen_row = row + 1
        
        # 打印行号
        stdscr.addstr(screen_row, 0, f"{row + 1:2d} ")
        
        # 打印棋盘内容
        row_str = " ".join(board[row])
        stdscr.addstr(screen_row, 3, row_str)
        
        # 打印右侧行号
        stdscr.addstr(screen_row, 4 + 2*19, f" {row + 1}")
    
    # 打印底部列标
    stdscr.addstr(20, 0, col_labels)
    
    # 打印当前步数、总步数、当前棋子颜色和当前棋谱
    status_line = (
        f"Use arrows to navigate, 'q' to quit. | "
        f"Move {current_move + 1}/{total_moves} | "
        f"{current_color} | "
        f"{current_move_info}"
    )
    stdscr.addstr(21, 0, status_line)
    
    # 刷新屏幕
    stdscr.refresh()

def main(stdscr, sgf_file):
    curses.curs_set(0)  # 隐藏光标
    
    # 读取SGF文件
    with open(sgf_file, "r") as file:
        sgf_content = file.read()
    
    # 解析棋步
    moves = parse_sgf(sgf_content)
    total_moves = len(moves)
    
    # 创建一个空白棋盘
    board = [['+' for _ in range(19)] for _ in range(19)]
    
    current_move = 0
    update_board(board, moves, current_move)
    current_color = 'B' if current_move % 2 == 0 else 'W'
    current_move_info = moves[current_move] if current_move < total_moves else ""
    draw_board(stdscr, board, current_move, total_moves, current_color, current_move_info)
    
    while True:
        key = stdscr.getch()
        
        if key == curses.KEY_RIGHT:  # 下一步
            if current_move < total_moves - 1:
                current_move += 1
        elif key == curses.KEY_LEFT:  # 上一步
            if current_move > 0:
                current_move -= 1
        elif key == curses.KEY_HOME:  # 第一步
            current_move = 0
        elif key == curses.KEY_END:  # 最后一步
            current_move = total_moves - 1
        elif key == curses.KEY_PPAGE:  # 上10步
            current_move = max(0, current_move - 10)
        elif key == curses.KEY_NPAGE:  # 下10步
            current_move = min(total_moves - 1, current_move + 10)
        elif key == ord('q'):  # 退出
            break
        
        # 更新棋盘
        update_board(board, moves, current_move)
        current_color = 'B' if current_move % 2 == 0 else 'W'
        current_move_info = moves[current_move] if current_move < total_moves else ""
        draw_board(stdscr, board, current_move, total_moves, current_color, current_move_info)

def update_board(board, moves, current_move):
    # 清空棋盘
    for row in range(19):
        for col in range(19):
            board[row][col] = '+'
    
    for i, move in enumerate(moves[:current_move + 1]):
        row, col = coord_to_board(move)
        if row is None or col is None:
            continue
        if i % 2 == 0:  # 黑子
            board[row][col] = '●'
        else:  # 白子
            board[row][col] = '○'

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python script.py <sgf_file>")
        sys.exit(1)
    
    sgf_file = sys.argv[1]
    curses.wrapper(main, sgf_file)